﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
using KFGame;

public class KFSocketPoll
{
    private static byte[] m_MaxOnePackBuff = new byte[1024];

    public static int port = 8888;

    public static string IpStr = "0.0.0.0";

    private static Socket serverSocket;

    public static int linknumber = 10;

    public static ArrayList
        m_listenSocketList = new System.Collections.ArrayList();

    public static ArrayList
        m_DeleteSocketList = new System.Collections.ArrayList();

    private Thread m_ReciveThread;

    private Mutex m_Mutex = new Mutex();

    public delegate void OnReceive(Socket socket, ByteBuffer buff);

    public OnReceive GetReceive;

    private static bool enter = true;

    private static KFSocketPoll poll;

    //分配用户ID
    public static int clientUserIndex = 0;

    public static KFSocketPoll instantiation()
    {
        if (poll == null) poll = new KFSocketPoll();
        return poll;
    }

    public KFSocketPoll()
    {
    }

    public void Start()
    {
        enter = true;

        // m_ReciveThread = new Thread(Epoll_ReceiveMessage);
        //  m_ReciveThread.Start();
        ServerListen();
        serverstart();
    }

    public void Close()
    {
        enter = false;
    }

    public void ServerListen()
    {
        IPAddress ip = IPAddress.Parse(IpStr);
        IPEndPoint ip_end_point = new IPEndPoint(ip, port);

        //创建服务器Socket对象，并设置相关属性
        serverSocket =
            new Socket(AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp);

        //绑定ip和端口
        serverSocket.Bind(ip_end_point);

        //设置最长的连接请求队列长度
        serverSocket.Listen(linknumber);
        Debug.Log("启动server监听成功");
    }

    public void Epoll_ReceiveMessage()
    {
        MonoBehaviour.print("开启服务器接收 ");

        //try
        {
            while (enter)
            {
                Thread.Sleep(1);

                FindScokets();

                if (0 == m_listenSocketList.Count) continue;

                readScokets();

                deleteScokets();
            }
        }

        BaseRelease();
    }

    private static Dictionary<string, Socket>
        clientSockets = new Dictionary<string, Socket>();

    public Socket GetCilent(string ip)
    {
        return clientSockets[ip];
    }

    public void removerOverSocket()
    {
        foreach (KeyValuePair<string, Socket> kv in clientSockets)
        {
            if (kv.Value == null || !kv.Value.Connected)
                clientSockets.Remove(kv.Key);
        }
    }

    private void serverstart()
    {
        Thread thread = new Thread(ClientConnectListen);
        thread.Start();
    }

    /// <summary>
    /// 客户端连接请求监听
    /// </summary>
    private void ClientConnectListen()
    {
        while (enter)
        {
            //为新的客户端连接创建一个Socket对象
            Socket clientSocket = serverSocket.Accept();

            clientUserIndex++;

            try
            {
                //向连接的客户端发送连接成功的数据
                ByteBuffer buffer = new ByteBuffer();
                buffer.WriteString("0|Connected-KFServer|" + clientUserIndex);
                clientSocket.Send(WriteMessage(buffer.ToBytes()));
            }
            catch (Exception ex)
            {
                Debug.LogError("link server send back error：" + ex.ToString());
            }

            //每个客户端连接创建一个线程来接受该客户端发送的消息
            Thread thread = new Thread(RecieveMessage);
            thread.Start(clientSocket);

            //clientPool.Add(thread);
            Debug.Log("客户端连接 :" + clientSocket.RemoteEndPoint.ToString());

            clientSockets
                .Add(clientSocket.RemoteEndPoint.ToString(), clientSocket);

            removerOverSocket();
        }
    }

    /// <summary>
    /// 数据转换，网络发送需要两部分数据，一是数据长度，二是主体数据
    /// </summary>
    /// <param name="message"></param>
    /// <returns></returns>
    private static byte[] WriteMessage(byte[] message)
    {
        MemoryStream ms = null;
        using (ms = new MemoryStream())
        {
            ms.Position = 0;
            BinaryWriter writer = new BinaryWriter(ms);
            ushort msglen = (ushort)message.Length;
            writer.Write(msglen);
            writer.Write(message);
            writer.Flush();
            return ms.ToArray();
        }
    }

    /// <summary>
    /// 接收指定客户端Socket的消息
    /// </summary>
    /// <param name="clientSocket"></param>
    private void RecieveMessage(object clientSocket)
    {
        Socket mClientSocket = (Socket)clientSocket;
        byte[] m_MaxOnePackBuff = new byte[1024];
        while (enter)
        {
            try
            {
                int rnum = mClientSocket.Receive(m_MaxOnePackBuff);
                Debug
                    .Log("接收 " +
                    mClientSocket.RemoteEndPoint.ToString() +
                    " : " +
                    rnum);
                if (rnum == 0) continue;

                Debug
                    .Log("接收客户端消息， 长度为 " +
                    mClientSocket.RemoteEndPoint.ToString() +
                    ":" +
                    rnum);
                ByteBuffer buff = new ByteBuffer(m_MaxOnePackBuff);

                //数据长度
                int len = buff.ReadShort();

                if (GetReceive != null) GetReceive(mClientSocket, buff);
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message);
                if (mClientSocket.Connected)
                {
                    mClientSocket.Shutdown(SocketShutdown.Both);
                    mClientSocket.Close();
                }
                break;
            }
        }
    }

    protected void readScokets()
    {
        Socket.Select(m_listenSocketList, null, null, 1000);
        try
        {
            for (int i = 0; i < m_listenSocketList.Count; ++i)
            {
                Socket mClient = (Socket)m_listenSocketList[i];

                //通过clientSocket接收数据
                //是否连接
                if (mClient == null) continue;
                if (!mClient.Connected) continue;

                int mReceiveNumber = mClient.Receive(m_MaxOnePackBuff);
                ByteBuffer mClientSendBuff = new ByteBuffer(m_MaxOnePackBuff);

                // 没有信息
                if (0 == mReceiveNumber) continue;

                if (mReceiveNumber > 0)
                {
                    Debug
                        .LogError(m_listenSocketList.Count +
                        "收到消息" +
                        mReceiveNumber);

                    Lock();
                    if (GetReceive != null)
                        GetReceive(mClient, mClientSendBuff);
                    UnLock();
                    continue;
                }

                MonoBehaviour
                    .print("one connect recive a error num: " +
                    mReceiveNumber.ToString());
            }
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.Message);
        }
    }

    protected ArrayList FindScokets()
    {
        m_listenSocketList.Clear();
        foreach (Socket socket in clientSockets.Values)
        {
            if (socket == null) continue;

            if (!socket.Connected)
            {
                Debug.LogError("废弃链接");
                m_DeleteSocketList.Add(socket);
                continue;
            }

            m_listenSocketList.Add(socket);
        }

        return m_listenSocketList;
    }

    protected void deleteScokets()
    {
        Lock();
        for (int i = 0; i < m_DeleteSocketList.Count; ++i)
        {
            Socket mClient = (Socket)m_DeleteSocketList[i];

            if (mClient == null) continue;

            mClient.Close();
            clientSockets.Remove(mClient.RemoteEndPoint.ToString());
            Debug.LogError("删除------" + mClient.RemoteEndPoint.ToString());
        }
        m_DeleteSocketList.Clear();
        UnLock();
    }

    protected void Lock()
    {
        m_Mutex.WaitOne();
    }

    protected void UnLock()
    {
        m_Mutex.ReleaseMutex();
    }

    public void BaseRelease()
    {
        m_Mutex.Close();
    }

    ///
    /// 给所有用户发信息
    public void SendAllMessage(string data)
    {
        ByteBuffer buffer = new ByteBuffer();
        buffer.WriteString(data);
        byte[] datas = WriteMessage(buffer.ToBytes());

        foreach (KeyValuePair<string, Socket> kv in clientSockets)
        {
            if (kv.Value == null || !kv.Value.Connected)
            {
                clientSockets.Remove(kv.Key);
                continue;
            }
            try
            {
                kv.Value.Send(datas);
            }
            catch
            {
                kv.Value.Close();
            }
        }
    }

    /// <summary>
    /// 发送数据给客戶端
    /// </summary>
    public static void SendMessage(Socket clientSocket, string data)
    {
        if (clientSocket == null) return;

        if (!clientSocket.Connected) return;

        try
        {
            ByteBuffer buffer = new ByteBuffer();
            buffer.WriteString(data);
            clientSocket.Send(WriteMessage(buffer.ToBytes()));
        }
        catch
        {
            clientSocket.Close();
        }
    }
}
